/*
 * Copyright (c) 2024, Qi Yaolong.
 * dragon@hbu.edu.cn
 * HeBei University, China.
 * 
 * 简体中文
 * 保留所有权利。除非符合（遵守）以下条款，否则您不得使用此文件：
 * 
 * 禁止任何未经授权的个人或组织以任何形式将本程序及其附属资料、创新、创意、架构设计、算法、衍生作品
 * 等用于任何商业目的、盈利活动、各类竞赛(比赛)、直播教学、录播教学、线下课程、书籍编写、教材编写、
 * 会议、培训、公益活动、项目课题、毕业设计、毕业论文、学术论文等。
 * 
 * 本程序由版权持有人和贡献人“按原样”提供，不提供任何明示或暗示担保，包括但不局限于对适销性和特定
 * 用途适合性的暗示担保。在任何情况下，版权持有人或贡献人对因使用本程序而导致的任何直接、间接、附带、
 * 特殊、典型或后果性损害（包括但不限于购买替代商品或服务；使用损失、数据丢失或利润损失；业务中断）
 * 不承担任何责任，无论其如何产生，也不论其责任理论为何，无论是合同、严格责任还是侵权（包括疏忽或
 * 其他），即使已告知此类损害的可能性。
 * 
 * English
 * All rights reserved. You may NOT use this file except in compliance with the
 * following terms:
 * 
 * IT IS PROHIBITED FOR ANY UNAUTHORIZED PERSON OR ENTITY TO USE THIS PROGRAM AND 
 * ITS ANCILLARY DATA, INNOVATIONS, CONCEPTS, ARCHITECTURE DESIGN, ALGORITHMS, 
 * DERIVED WORKS, ETC., IN ANY FORM FOR COMMERCIAL PURPOSES, PROFIT-MAKING 
 * ACTIVITIES, VARIOUS COMPETITIONS (CONTESTS), LIVE TEACHING, PRE-RECORDED 
 * LESSONS, OFFLINE COURSES, BOOK WRITING, CONFERENCES, TRAININGS, PUBLIC WELFARE 
 * ACTIVITIES, PROJECTS, TOPICS, GRADUATION DESIGNS, DISSERTATIONS, THESES, AND 
 * OTHER APPLICATIONS.
 * 
 * THIS PROGRAM IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS PROGRAM, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "sle_errcode.h"
#include "sle_connection_manager.h"
#include "sle_device_discovery.h"
#include "ohos_sle_common.h"
#include "ohos_sle_errcode.h"
#include "ohos_sle_ssap_server.h"
#include "ohos_sle_ssap_client.h"
#include "ohos_sle_device_discovery.h"
#include "ohos_sle_connection_manager.h"
#include "errcode.h"
#include "../global_settings.h" 
#include "sle_client.h"
#include "sle_server_adv.h"
#include "sle_server.h"

static sle_announce_seek_callbacks_t g_sle_seek_cbk = {0};

static SleConnectionCallbacks g_sle_connect_cbk = {0};

extern void sle_client_sle_enable_cbk(errcode_t status);
extern void sle_client_sle_disable_cbk(errcode_t status);
extern void sle_client_seek_enable_cbk(errcode_t status);
extern void sle_client_seek_result_cbk(SleSeekResultInfo *seek_result_data);
extern void sle_client_seek_disable_cbk(errcode_t status);
extern void sle_server_sle_enable_cbk(errcode_t status);
extern void sle_server_sle_disable_cbk(errcode_t status);
extern void sle_server_announce_enable_cbk(uint32_t announce_id, errcode_t status);
extern void sle_server_announce_disable_cbk(uint32_t announce_id, errcode_t status);
extern void sle_server_announce_terminal_cbk(uint32_t announce_id);

static void sle_enable_cbk(errcode_t status)
{
    sle_server_sle_enable_cbk(status); 
    sle_client_sle_enable_cbk(status); 
}

static void sle_disable_cbk(errcode_t status)
{
    sle_server_sle_disable_cbk(status); 
    sle_client_sle_disable_cbk(status); 
}

static errcode_t sle_announce_seek_register_cbks(void)
{
    errcode_t ret;

    g_sle_seek_cbk.sle_enable_cb = sle_enable_cbk;   
    g_sle_seek_cbk.sle_disable_cb = sle_disable_cbk; 

    g_sle_seek_cbk.announce_enable_cb = sle_server_announce_enable_cbk;     
    g_sle_seek_cbk.announce_disable_cb = sle_server_announce_disable_cbk;   
    g_sle_seek_cbk.announce_terminal_cb = sle_server_announce_terminal_cbk; 

    g_sle_seek_cbk.seek_enable_cb = sle_client_seek_enable_cbk;   
    g_sle_seek_cbk.seek_result_cb = sle_client_seek_result_cbk;   
    g_sle_seek_cbk.seek_disable_cb = sle_client_seek_disable_cbk; 

    return sle_announce_seek_register_callbacks(&g_sle_seek_cbk); 
}

extern void sle_client_connect_state_changed_cbk(uint16_t conn_id, const SleAddr *addr, SleAcbStateType conn_state, SlePairStateType pair_state, SleDiscReasonType disc_reason);
extern void sle_server_connect_state_changed_cbk(uint16_t conn_id, const SleAddr *addr, SleAcbStateType conn_state, SlePairStateType pair_state, SleDiscReasonType disc_reason);
extern void sle_server_connect_param_update_req_cbk(uint16_t conn_id, errcode_t status, const sle_connection_param_update_req_t *param);
extern void sle_server_connect_param_update_cbk(uint16_t conn_id, errcode_t status, const SleConnectionParamUpdateEvt *param);
extern void sle_server_auth_complete_cbk(uint16_t conn_id, const SleAddr *addr, errcode_t status, const sle_auth_info_evt_t *evt);
extern void sle_server_pair_complete_cbk(uint16_t conn_id, const SleAddr *addr, errcode_t status);
extern void sle_server_read_rssi_cbk(uint16_t conn_id, int8_t rssi, errcode_t status);

static void connect_state_changed_cbk(uint16_t conn_id, const SleAddr *addr,
                                      SleAcbStateType conn_state, SlePairStateType pair_state, SleDiscReasonType disc_reason)
{
    printf("[connect_state_changed_cbk] mac: %02x:%02x:%02x:%02x:%02x:%02x\r\n",
           addr->addr[0], addr->addr[1], addr->addr[2], addr->addr[3], addr->addr[4], addr->addr[5]);

    uint8_t remote_server_addr_match = 0;
    SleAddr *remote_server_addr = sle_get_remote_server_addr();
    for (uint8_t i = 0; i < sle_get_num_remote_server_addr(); i++)
    {
        if (memcmp(addr, &remote_server_addr[i], sizeof(SleAddr)) == 0) 
        {
            remote_server_addr_match = 1;
            break;
        }
    }

    if (remote_server_addr_match == 0) 
    {
        sle_server_connect_state_changed_cbk(conn_id, addr, conn_state, pair_state, disc_reason);
    }
    else 
    {
        sle_client_connect_state_changed_cbk(conn_id, addr, conn_state, pair_state, disc_reason);
    }
}

static errcode_t sle_conn_register_cbks(void)
{
    errcode_t ret;

    g_sle_connect_cbk.connectStateChangedCb = connect_state_changed_cbk; 

    g_sle_connect_cbk.connectParamUpdateReqCb = sle_server_connect_param_update_req_cbk; 
    g_sle_connect_cbk.connectParamUpdateCb = sle_server_connect_param_update_cbk;        
    g_sle_connect_cbk.authCompleteCb = sle_server_auth_complete_cbk;                     
    g_sle_connect_cbk.pairCompleteCb = sle_server_pair_complete_cbk;                     
    g_sle_connect_cbk.readRssiCb = sle_server_read_rssi_cbk;                             

    return SleConnectionRegisterCallbacks(&g_sle_connect_cbk); 
}

errcode_t sle_register_common_cbks()
{
    errcode_t ret;

    ret = sle_announce_seek_register_cbks();
    if (ret != ERRCODE_SLE_SUCCESS)
    {
        printf("[register_cbks] sle_announce_seek_register_cbks fail :%x\r\n", ret);
        return ret;
    }

    ret = sle_conn_register_cbks();
    if (ret != ERRCODE_SLE_SUCCESS)
    {
        printf("[register_cbks] sle_conn_register_cbks fail :%x\r\n", ret);
        return ret;
    }

    return ERRCODE_SLE_SUCCESS;
}
